{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 前置 `++i` vs 后置 `i++`\n",
    "\n",
    "- **语义**：前置先自增再返回引用；后置返回自增前的值（需存临时副本）。\n",
    "- **模板选择**：若类型自定义了 `operator++`，优先用前置版本，可避免额外复制和潜在的 `const` 限制。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "after ++i: i=6, pre=6\n",
      "after j++: j=6, post=5\n"
     ]
    }
   ],
   "source": [
    "#include <iostream>\n",
    "\n",
    "{\n",
    "    int i = 5;\n",
    "    int& pre  = ++i;  // i == 6, pre 引用 i\n",
    "    std::cout << \"after ++i: i=\" << i << \", pre=\" << pre << '\\n';\n",
    "\n",
    "    int j = 5;\n",
    "    int post = j++;   // post == 5, j == 6\n",
    "    std::cout << \"after j++: j=\" << j << \", post=\" << post << '\\n';\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 序列点 / Sequenced Before & C++17 的影响\n",
    "\n",
    "- 现代术语：**sequenced-before/after** 描述求值顺序。若两个副作用未被顺序约束，表达式可能导致未定义行为。\n",
    "- C++17 明确许多以前未规定的求值顺序（如函数实参、`&&`, `||`, `?:`, `,` 等），减少了因顺序不定而产生的 UB。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "input_line_10:7:17: warning: unsequenced modification and access to 'b' [-Wunsequenced]\n",
      "    int c = b + ++b; // C++17 仍是 UB：b 被无序修改与读取\n",
      "            ~   ^\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sequenced: 2\n",
      "UB result may vary: 1\n"
     ]
    }
   ],
   "source": [
    "#include <iostream>\n",
    "\n",
    "void observe(const char* tag, int x) { std::cout << tag << x << '\\n'; }\n",
    "\n",
    "{\n",
    "    int a = 0;\n",
    "    observe(\"Sequenced: \", (a = 1, a + 1)); // 逗号运算符规定顺序\n",
    "\n",
    "    int b = 0;\n",
    "    int c = b + ++b; // C++17 仍是 UB：b 被无序修改与读取\n",
    "    observe(\"UB result may vary: \", c);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 未指定 / 实现定义 / 未定义 行为\n",
    "\n",
    "- **未指定（unspecified）**：实现可选多个结果，不需记录。例：函数实参求值顺序（C++17 前大多未指明）。\n",
    "- **实现定义（implementation-defined）**：实现必须选择并文档化。例：`int` 占用字节数、右移负数的行为（算术/逻辑）。\n",
    "- **未定义（undefined）**：标准不限制结果，可发生任何现象。例：访问已释放内存、整数溢出（有符号）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "unspecified example: 3\n",
      "implementation-defined bit-width result: 2147483648\n",
      "undefined example: -2147483648\n"
     ]
    }
   ],
   "source": [
    "#include <iostream>\n",
    "\n",
    "int side_effect(int& x) { x += 1; return x; }\n",
    "\n",
    "{\n",
    "    int x = 0;\n",
    "    // 未指定：两个函数参数的求值顺序可能不同\n",
    "    int unspecified = side_effect(x) + side_effect(x);\n",
    "    std::cout << \"unspecified example: \" << unspecified << '\\n';\n",
    "\n",
    "    unsigned u = 1u << 31; // 实现需规定 unsigned 位宽\n",
    "    std::cout << \"implementation-defined bit-width result: \" << u << '\\n';\n",
    "\n",
    "    int overflow = 2147483647;\n",
    "    overflow += 1; // 有符号溢出 => UB，结果不可依赖\n",
    "    std::cout << \"undefined example: \" << overflow << '\\n';\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 整数提升（integer promotion）\n",
    "\n",
    "- 当较小整型（`bool`, `char`, `signed/unsigned char`, `short` 等）参与算术或位运算时，会提升为 `int` 或 `unsigned int`（若 `int` 无法表示其所有值，则用 `unsigned int`）。\n",
    "- 影响：`char/short` 在表达式中通常先变为 `int` 再运算，可能改变符号扩展方式。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "type of sum is int: 1\n",
      "value = 0\n",
      "expr (int) = 260\n"
     ]
    }
   ],
   "source": [
    "#include <iostream>\n",
    "#include <type_traits>\n",
    "\n",
    "{\n",
    "    char c = -1;\n",
    "    auto sum = c + 1; // c 被提升为 int\n",
    "    std::cout << \"type of sum is int: \"\n",
    "              << std::is_same<decltype(sum), int>::value << '\\n';\n",
    "    std::cout << \"value = \" << sum << '\\n';\n",
    "\n",
    "    unsigned char uc = 250;\n",
    "    auto expr = uc + 10; // 提升为 int，再计算\n",
    "    std::cout << \"expr (int) = \" << expr << '\\n';\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# `constexpr` vs `const`\n",
    "\n",
    "- `const` 仅表示不可修改；值可以在运行期确定。\n",
    "- `constexpr` 要求表达式在编译期可求值（若所有条件满足），可用于数组大小、模板实参等。\n",
    "- `constexpr` 变量默认为 `const`，并能确保用于编译期上下文。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "// https://godbolt.org/z/jGbKf484f\n",
    "\n",
    "#include <array>\n",
    "#include <iostream>\n",
    "\n",
    "int runtime_const();\n",
    "\n",
    "int main() {\n",
    "    const int x = runtime_const(); // 运行期才能得值\n",
    "    // constexpr int y = runtime_const(); // 编译失败：非编译期常量\n",
    "\n",
    "    constexpr int z = 10;\n",
    "    std::array<int, z> arr{}; // 需要编译期常量\n",
    "    std::cout << \"arr size = \" << arr.size() << '\\n';\n",
    "}\n",
    "\n",
    "int runtime_const() { return 42; }"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# * 临时对象生命周期延长\n",
    "\n",
    "- **临时对象绑定到 `const T&` 或 `T&&`（其中 `T&&` 直接绑定该临时）** 可以延长生命周期，但**只在绑定发生的那个作用域内**有效。\n",
    "- **延长只对“直接绑定的引用”有效**，延长到这个引用的生命周期结束，但**不能跨函数返回边界**：函数里创建的临时绑定到局部 `const T&`，离开函数时就销毁，即使返回这个引用也会悬空。\n",
    "- `T&&` 绑定临时本身也会延长（与 `const T&` 相同），但若 `T&&` 再转发/移动到别处，需要看新的绑定。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "#include <iostream>\n",
    "\n",
    "struct Widget {\n",
    "    Widget() { std::cout << \"Widget()\\n\"; }\n",
    "    ~Widget() { std::cout << \"~Widget()\\n\"; }\n",
    "};"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "input_line_9:2:12: warning: returning reference to local temporary object [-Wreturn-stack-address]\n",
      "    return Widget(); // 临时绑定到 const 引用, 延长到函数结束返回值对象\n",
      "           ^~~~~~~~\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Widget()\n",
      "~Widget()\n",
      "Still alive\n"
     ]
    }
   ],
   "source": [
    "const Widget& make_ref() {\n",
    "    return Widget(); // 这里临时绑定到返回值引用，但函数结束就销毁\n",
    "}\n",
    "\n",
    "{\n",
    "    const Widget& ref = make_ref(); // ref 成为悬空引用（dangling）\n",
    "    std::cout << \"Still alive\\n\"; // 未定义行为\n",
    "}"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "C++17",
   "language": "C++17",
   "name": "xcpp17"
  },
  "language_info": {
   "codemirror_mode": "text/x-c++src",
   "file_extension": ".cpp",
   "mimetype": "text/x-c++src",
   "name": "c++",
   "version": "17"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
